import React, { useState, useEffect, useRef, useCallback } from 'react';
import { Card, Image, Spin } from 'antd';
import styles from './Waterfall.module.css';

/**
 * 图片项接口定义
 * @interface ImageItem
 * @property {string} id - 唯一标识符
 * @property {string} url - 图片URL地址
 * @property {string} title - 图片标题
 * @property {number} height - 图片高度
 * @property {boolean} [loading] - 图片加载状态
 */
interface ImageItem {
  id: string;
  url: string;
  title: string;
  height: number;
  loading?: boolean;
}

/**
 * 瀑布流组件
 * 实现了以下功能：
 * 1. 响应式多列布局
 * 2. 图片加载动画效果
 * 3. 无限滚动加载
 * 4. 加载状态管理
 */
const Waterfall: React.FC = () => {
  // 存储所有图片数据
  const [images, setImages] = useState<ImageItem[]>([]);
  // 控制整体加载状态
  const [loading, setLoading] = useState(false);
  // 是否还有更多数据可加载
  const [hasMore, setHasMore] = useState(true);
  // 用于监测滚动触底的ref
  const loadingRef = useRef<HTMLDivElement>(null);
  // 当前页码
  const pageRef = useRef(1);

  /**
   * 生成模拟数据
   * @param page - 页码
   * @returns 生成的图片数据数组
   */
  const generateMockData = (page: number) => {
    const startIndex = (page - 1) * 20;
    return Array.from({ length: 20 }, (_, index) => ({
      id: `${startIndex + index}`,
      // 使用随机参数确保每次请求的图片不同
      url: `https://picsum.photos/400/${Math.floor(Math.random() * 200 + 400)}?random=${startIndex + index}`,
      title: `设计模板 ${startIndex + index + 1}`,
      height: Math.floor(Math.random() * 200 + 400),
      loading: true, // 初始状态为加载中
    }));
  };

  /**
   * 处理单张图片加载完成的回调
   * @param imageId - 加载完成的图片ID
   */
  const handleImageLoad = (imageId: string) => {
    setImages(prevImages => 
      prevImages.map(img => 
        img.id === imageId ? { ...img, loading: false } : img
      )
    );
  };

  /**
   * 加载更多数据
   * 使用useCallback优化性能，避免不必要的重渲染
   */
  const loadMoreData = useCallback(async () => {
    // 防止重复加载
    if (loading || !hasMore) return;
    
    setLoading(true);
    try {
      // 模拟网络请求延迟
      await new Promise(resolve => setTimeout(resolve, 1000));
      const newData = generateMockData(pageRef.current);
      
      // 将新数据添加到现有数据末尾
      setImages(prev => [...prev, ...newData]);
      pageRef.current += 1;
      
      // 模拟数据上限，超过5页就没有更多数据
      if (pageRef.current > 5) {
        setHasMore(false);
      }
    } finally {
      setLoading(false);
    }
  }, [loading, hasMore]);

  /**
   * 组件挂载时加载初始数据
   */
  useEffect(() => {
    loadMoreData();
  }, []);

  /**
   * 设置无限滚动监听
   * 使用 IntersectionObserver 监测加载触发器是否进入视口
   */
  useEffect(() => {
    const options = {
      root: null, // 使用视口作为根元素
      rootMargin: '0px', // 无边距
      threshold: 0.1, // 当10%的元素可见时触发
    };

    const observer = new IntersectionObserver(entries => {
      if (entries[0].isIntersecting) {
        loadMoreData();
      }
    }, options);

    if (loadingRef.current) {
      observer.observe(loadingRef.current);
    }

    // 清理函数，组件卸载时断开观察器
    return () => observer.disconnect();
  }, [loadMoreData]);

  /**
   * 渲染图片列表
   * @returns 图片卡片列表
   */
  const renderImages = () => {
    return images.map((image) => (
      <Card
        key={image.id}
        className={styles.imageCard}
        hoverable
        bordered={false}
        cover={
          <div className={`${styles.imageWrapper} ${image.loading ? styles.loading : ''}`}>
            <Image
              src={image.url}
              alt={image.title}
              className={styles.cardImage}
              preview={false}
              onLoad={() => handleImageLoad(image.id)}
            />
          </div>
        }
      >
        <div className={styles.cardContent}>
          <h4 className={styles.cardTitle}>{image.title}</h4>
        </div>
      </Card>
    ));
  };

  return (
    <>
      <div className={styles.waterfall}>
        {renderImages()}
      </div>
      {/* 加载触发器 */}
      <div ref={loadingRef} className={styles.loadingMore}>
        {loading ? (
          <>
            <Spin /> 加载中...
          </>
        ) : hasMore ? (
          '滚动加载更多'
        ) : (
          '没有更多了'
        )}
      </div>
    </>
  );
};

export default Waterfall; 